package com.ding.easycontroller.controller;

import com.ding.easycontroller.helper.EcMultiPartRequestImpl;
import com.ding.easycontroller.helper.EcSession;
import com.ding.easycontroller.model.R;
import com.ding.easycontroller.service.DaoService;
import com.ding.easycontroller.service.PluginService;
import com.ding.easycontroller.service.ServiceService;
import com.ding.easycontroller.utils.ConsoleUtils;
import com.ding.easycontroller.utils.RequestUtils;
import com.ding.easycontroller.utils.ResponseUtils;
import com.ding.easycontroller.work.Dao;
import com.ding.easycontroller.work.Service;
import easycontroller.plugin.Plugin;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Reader;
import java.io.Writer;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RestController
@RequestMapping("/_config/edit")
public class _EditController {

    @Autowired
    private ServiceService serviceService;

    @Autowired
    private DaoService daoService;

    @Autowired
    private PluginService pluginService;

    @GetMapping("/loadHint/controller")
    R loadHintController() {
        Map<String, Object> hint = new HashMap<>();
        hint.put("_controller", "__function");
        addBase(hint);
        addRequestBase(hint);
        addService(hint);
        addDao(hint);
        addPlugins(hint);
        return R.ok(hint);
    }
    @GetMapping("/loadHint/websocket")
    R loadHintWebSocket() {
        Map<String, Object> hint = new HashMap<>();
        hint.put("_onMessage", "__function");
        hint.put("_onOpen", "__function");
        hint.put("_onClose", "__function");
        addBase(hint);
        addWebSocket(hint);
        addService(hint);
        addDao(hint);
        addPlugins(hint);
        return R.ok(hint);
    }

    @GetMapping("/loadHint/filter")
    R loadHintFilter() {
        Map<String, Object> hint = new HashMap<>();
        hint.put("_before", "__function");
        hint.put("_after", "__function");
        hint.put("_default", "__function");
        addBase(hint);
        addRequestBase(hint);
        addService(hint);
        addDao(hint);
        addPlugins(hint);
        return R.ok(hint);
    }

    @GetMapping("/loadHint/service")
    R loadHintService() {
        Map<String, Object> hint = new HashMap<>();
        addBase(hint);
        hint.put("_service", "__function");
        addService(hint);
        addDao(hint);
        addPlugins(hint);
        return R.ok(hint);
    }

    @GetMapping("/loadHint/dao")
    R loadHintDao() {
        Map<String, Object> hint = new HashMap<>();
        hint.put("_dao", "__function");
        addBase(hint);
        addService(hint);
        addDao(hint);
        addPlugins(hint);
        return R.ok(hint);
    }

    private void addBase(Map<String, Object> hint) {
        addClass(hint, "console", ConsoleUtils.class);
        Map<String, Object> utils = new HashMap<>();
        addClass(utils, "response", ResponseUtils.class);
        addClass(utils, "request", RequestUtils.class);
        hint.put("utils", utils);
    }

    private void addPlugins(Map<String, Object> hint) {
        List<Plugin> plugins = pluginService.getEnablePlugins();
        Map<String, Object> pph = new HashMap<>();
        for (Plugin plugin : plugins) {
            Class<? extends Plugin> pluginClass = plugin.getClass();
            addClass(pph, plugin.getName(), pluginClass);
        }
        hint.put("plugins", pph);
    }

    private void addService(Map<String, Object> hint) {

        List<Service> services = serviceService.listAll();

        Map<String, Object> map = new HashMap<>();
        //添加所有服务
        for (Service service : services) {
            map.put(service.getName(), "__object");
        }
        hint.put("services", map);
    }

    private void addDao(Map<String, Object> hint) {
        Map<String, Object> map = new HashMap<>();
        List<Dao> daos = daoService.listAll();

        //添加所有服务
        for (Dao dao : daos) {
            map.put(dao.getName(), "__object");
        }
        hint.put("daos", map);
    }

    private void addRequestBase(Map<String, Object> hint) {

        addClass(hint, "_req", EcMultiPartRequestImpl.class);
        addClass(hint, "_resp", HttpServletResponse.class);
        addClass(hint, "_reader", Reader.class);
        addClass(hint, "_writer", Writer.class);
        addClass(hint, "_output", OutputStream.class);
        addClass(hint, "_input", InputStream.class);
        addClass(hint, "_session", HttpSession.class);

        //添加对象
        hint.put("_reqHeads", "__object");
        hint.put("_respHeads", "__object");
        hint.put("_reader", "__object");
        hint.put("_params", "__object");
        hint.put("_pathValues", "__object");
        hint.put("_status", "__object");
    }

    private void addWebSocket(Map<String, Object> hint) {
        hint.put("_msg", "__object");
        hint.put("_pathValues", "__object");
        addClass(hint, "_session", EcSession.class);
    }

    private void addClass(Map<String, Object> hint, String name, Class<?> clazz) {
        List<String> list = readFunction(clazz);
        Map<String, Object> map = new HashMap<>();
        for (String s : list) {
            map.put(s, "__function");
        }
        hint.put(name, map);
    }

    private static List<String> readFunction(Class<?> clazz) {
        List<String> r = new ArrayList<>();
        Method[] methods = clazz.getMethods();
        for (Method method : methods) {
            int modifiers = method.getModifiers();

            if ((modifiers & 1) == 1) {
                r.add(method.getName());
            }
        }

        return r;
    }


}
